home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’93 / Don's Hacks / AppBar Source / AppBarUnit.p < prev    next >
Text File  |  1993-06-18  |  20KB  |  712 lines

  1. {
  2.     $Workfile:   AppBarComp.p  $
  3.     $Revision:   1.0  $
  4.  
  5.     This handles all of our pallette stuff.  Separated from AppBar.p for clarity.
  6.  
  7.     © 1993 CE Software, Inc.  All rights reserved.
  8.  
  9.     WHEN    WHO        WHAT
  10.  
  11. •••••
  12.     
  13. •••••
  14. }
  15.  
  16. UNIT AppBarUnit;
  17.  
  18. INTERFACE
  19.  
  20. USES Memtypes, Quickdraw, OSIntf, ToolIntf, PackIntf, MacPrint, GestaltEqu, Folders,
  21.     Errors, Notification, Processes, Aliases, TextServices, AppleEvents;
  22.  
  23. Function InitLayer:OSErr;
  24. Procedure CloseLayer;
  25. Procedure LayerIdleProc(var doneflag:boolean);
  26. Function myGNEFilter (result:integer; var event:EventRecord):integer;
  27.  
  28. Procedure DoOpenApp(AllowUserInteraction:Boolean);
  29.  
  30. IMPLEMENTATION
  31.  
  32. {$D+} {$R-}
  33.  
  34. CONST
  35.     kClosePallette=-1;
  36.     kRecalcWindow=-2;
  37.     
  38.     HiliteMode = $938; {[GLOBAL VAR]  used for color highlighting}
  39.     
  40.     MyItemWidth=22;
  41.     MyItemHeight=20;
  42.     MaxNumberIcons=20;
  43.  
  44. TYPE
  45.     MyAppInfo=record
  46.         name:str31;
  47.         TheType,TheCreator:OSType;
  48.         Thepsn:ProcessSerialNumber;
  49.         end;
  50.         
  51.     MyGlobals=record
  52.         StoredPalletteWindow:windowptr;            {MUST start our globals (TSMHelper assumes this}
  53.         MyProcess:        ProcessSerialNumber;
  54.         WhatToDo:        integer;                {Message to do stuff}
  55.         PalletteIcons:    integer;
  56.         BottomRight:        point;
  57.         TheIcon:        array[1..MaxNumberIcons] of MyAppInfo; {Names of icons in folder}
  58.         TempIcon:        packed array[1..kSmall8BitIconSize] of char;
  59.         LastProcess:    ProcessSerialNumber;
  60.         LastProcessIndex:    integer;
  61.         end;
  62.     MyGlobalsPtr=^MyGlobals;
  63.  
  64. Function Storage:MyGlobalsPtr; external;
  65.     {This routine holds some data within our data, so we don't have to worry about A5}
  66. Procedure HookUp; external;
  67.     {This connects our jGNE Event filter, necessary so that we can grab the events for our windoid}
  68. Procedure UnHook; external;
  69.     {This unconnects our jGNE Event filter, so that we can quit cleanly.}
  70.  
  71. {--------------------------------------------------------------------------
  72.     
  73.     Some color grapics utilities, to draw pretty stuff.
  74.     
  75.     PlotColorPtr
  76.         A simple routine to draw a color icon.
  77.     PlotBWPtr
  78.         A simple routine to draw a black and white icon (not using any color QuickDraw calls)
  79.     ColorRectDepth
  80.         Gets the "depth" of the rectangle, to know whether to plot color or B&W
  81.     
  82.         Not part of the layer stuff, used by our UpdateEvent handler.
  83.  
  84.  --------------------------------------------------------------------------}
  85. Procedure PlotColorPtr(wDepth,wFaceSize:integer; DestRect : Rect; p:ptr; themode:integer);
  86. type bitmapPtr=^bitmap;
  87. var hPixMap:PixMapHandle; pCurPort:grafptr;
  88. begin
  89.     
  90.     hPixMap:=NewPixMap;
  91.     MoveHHi(handle(hPixMap));
  92.     HLock(handle(hPixMap));
  93.     
  94.     with hPixMap^^ do begin
  95.         hRes:=$480000;
  96.         vRes:=$480000;
  97.         pixelType:=0;
  98.         planeBytes:=0;
  99.         bounds.top:=0;
  100.         bounds.left:=0;
  101.         bounds.bottom:=wFaceSize;
  102.         bounds.right:=wFaceSize;
  103.         pixelSize:=wDepth;
  104.         cmpCount:=wDepth;
  105.         rowBytes:=((wDepth*wFaceSize) div 8)+$8000;
  106.         baseAddr:=pointer(p);
  107.         end;
  108.     
  109.     DisposCTable(hPixMap^^.pmTable);
  110.     hPixMap^^.pmTable:=GetCTable(wDepth);
  111.     
  112.     GetPort(pCurPort);
  113.     CopyBits(bitmapPtr(hPixMap^)^, pCurPort^.portbits, hPixMap^^.bounds,
  114.         DestRect,themode,nil);
  115.     hPixMap^^.baseaddr:=nil;
  116.     hunlock(handle(hPixMap));
  117.     disposPixMap(hPixMap);
  118.     end;
  119.  
  120. Procedure PlotBWPtr(wFaceSize:integer; DestRect : Rect; p:ptr);
  121. var pCurPort:grafptr; mybitmap:bitmap;
  122. begin
  123.     with mybitmap do begin
  124.         bounds.top:=0;
  125.         bounds.left:=0;
  126.         bounds.bottom:=wFaceSize;
  127.         bounds.right:=wFaceSize;
  128.         rowBytes:=wFaceSize div 8;
  129.         baseAddr:=pointer(p);
  130.         end;
  131.     GetPort(pCurPort);
  132.     CopyBits(mybitmap, pCurPort^.portbits, mybitmap.bounds,DestRect,0,nil);
  133.     end;
  134.  
  135. Function ColorRectDepth(therect:rect):integer;
  136. var    response: LONGINT; r2:rect; thegd:GDHandle;
  137. begin
  138.     ColorRectDepth:=1;
  139.     if gestalt(gestaltQuickdrawVersion,response)=noerr then
  140.       if response>=gestalt8BitQD then begin {determine if we can use the color QD calls}
  141.         r2:=therect;
  142.         LocalToGlobal(r2.topleft);
  143.         LocalToGlobal(r2.botright);
  144.         thegd:=GetMaxDevice(r2);
  145.         if thegd<>nil then
  146.           ColorRectDepth:=thegd^^.gdPMap^^.pixelSize;
  147.         end;
  148.     end;
  149.  
  150. {--------------------------------------------------------------------------
  151.     
  152.     FSDTManRefNum
  153.         Utility routine to get the refnum used by the DeskTop Manager
  154.     
  155.         Not part of the layer stuff, used by our UpdateEvent handler.
  156.  
  157.  --------------------------------------------------------------------------}
  158. Function FSDTManRefNum(thevref:integer):integer;
  159. var    myDTPB:    DTPBRec;
  160.     io:OSErr;
  161. begin
  162.     myDTPB.ioNamePtr:=nil;
  163.     myDTPB.ioVRefNum:=thevref;
  164.     io:=PBDTGetPath(@myDTPB);
  165.     if io=NoErr then FSDTManRefNum:=myDTPB.ioDTRefnum
  166.         else FSDTManRefNum:=0;
  167.     end;
  168.  
  169. {--------------------------------------------------------------------------
  170.     
  171.     PlotFileIcon
  172.         Gets appropriate icon for a file (from the DeskTop Manager) and plots it.
  173.     
  174.         Not part of the layer stuff, used by our UpdateEvent handler.
  175.  
  176.  --------------------------------------------------------------------------}
  177. Procedure PlotFileIcon(which:integer);
  178. var    io:OSErr; flag:boolean; therect:rect;
  179.     
  180.     Procedure HandleDTMan;
  181.     var    myDTPB:    DTPBRec;
  182.         io:OSErr;
  183.         vindex,tempref:integer;
  184.         mypb:paramBlockRec;
  185.         vname:str63;
  186.         
  187.         Procedure TryBAndWDT;
  188.         begin
  189.             myDTPB.ioDTReqCount:=kSmallIconSize;
  190.             myDTPB.ioIconType:=kSmallIcon;
  191.             io:=PBDTGetIcon(@myDTPB,false);
  192.             if io=NoErr then begin
  193.                 with storage^ do
  194.                     PlotBWPtr(16,therect,@TempIcon);
  195.                 exit(PlotFileIcon);
  196.                 end;
  197.             end;
  198.         
  199.         Procedure TryColorDT;
  200.         begin
  201.             myDTPB.ioDTReqCount:=kSmall8BitIconSize;
  202.             myDTPB.ioIconType:=kSmall8BitIcon;
  203.             io:=PBDTGetIcon(@myDTPB,false);
  204.             if io=NoErr then begin
  205.                 with storage^ do
  206.                     PlotColorPtr(8,16,therect,@TempIcon,0);
  207.                 exit(PlotFileIcon);
  208.                 end
  209.                 else TryBAndWDT;
  210.             end;
  211.         
  212.     begin
  213.         vindex:=1;
  214.             repeat
  215.             with mypb do begin
  216.                 ioCompletion:=NIL;
  217.                 ioNameptr:=@vname;
  218.                 ioVRefNum:=0;
  219.                 ioVolIndex:=vindex;
  220.                 end;
  221.             io:=PBGetVInfo(@mypb,false);
  222.             if io=NoErr then begin
  223.                 tempref:=FSDTManRefNum(mypb.iovrefnum);
  224.                 if tempref<>0 then begin
  225.                     with storage^,myDTPB do begin
  226.                         ioDTRefNum:=tempref;
  227.                         ioTagInfo:=0;
  228.                         ioDTBuffer:=@TempIcon;
  229.                         ioFileCreator:=storage^.TheIcon[which].TheCreator;
  230.                         ioFileType:=storage^.TheIcon[which].TheType;
  231.                         end;
  232.                     if ColorRectDepth(therect)>2 then TryColorDT else TryBAndWDT;
  233.                     end;
  234.                 end;
  235.             vindex:=vindex+1;
  236.             until io<>NoErr;
  237.         end;
  238.     
  239.     Procedure HandleSpecialIcon(whichicon:integer);
  240.     var    h:handle;
  241.         Procedure TryBAndWSpecial;
  242.         begin
  243.             h:=GetResource('ics#',whichicon);  {Get the icon to the folder out of the system file}
  244.             if h<>nil then begin
  245.                 hlock(h);
  246.                 PlotBWPtr(16,therect,pointer(h^));
  247.                 hunlock(h);
  248.                 end;
  249.             end;
  250.         Procedure TryColorSpecial;
  251.         begin
  252.             h:=GetResource('ics8',whichicon);  {Get the icon to the folder out of the system file}
  253.             if h<>nil then begin
  254.                 hlock(h);
  255.                 PlotColorPtr(8,16,therect,pointer(h^),0);
  256.                 hunlock(h);
  257.                 end
  258.                 else TryBAndWSpecial;
  259.             end;
  260.     begin
  261.         if ColorRectDepth(therect)>2 then TryColorSpecial else TryBAndWSpecial;
  262.         exit(PlotFileIcon);
  263.         end;
  264.     
  265. begin
  266.     therect:=storage^.StoredPalletteWindow^.portrect;
  267.     with therect do begin
  268.         left:=(which-1)*MyItemWidth;
  269.         right:=left+MyItemWidth;
  270.         eraserect(therect);
  271.         
  272.         top:=(top+bottom-16) div 2;
  273.         bottom:=top+16;
  274.         left:=(left+right-16) div 2;
  275.         right:=left+16;
  276.         end;
  277.     {Maybe frame it}
  278.     with storage^ do io:=SameProcess(LastProcess,TheIcon[which].Thepsn,flag);
  279.     if flag then begin
  280.         insetrect(therect,-3,-3);
  281.         pensize(2,2);
  282.         framerect(therect);
  283.         pensize(1,1);
  284.         insetrect(therect,3,3);
  285.         end;
  286.     framerect(therect);
  287.             
  288.     HandleDTMan;
  289.     
  290.     if storage^.TheIcon[which].theType='APPL' then HandleSpecialIcon(-3996)
  291.         else HandleSpecialIcon(-4000)
  292.     end;
  293.  
  294. {--------------------------------------------------------------------------
  295.     
  296.     CloseThePallette
  297.         If we've got a window, close it.  Note just one call to close the service window.
  298.         This should only be called from the 'real' application, not from the event handler.
  299.         
  300.  
  301.  --------------------------------------------------------------------------}
  302. Procedure CloseThePallette;
  303. var    io:OSErr;
  304. begin
  305.     if storage^.StoredPalletteWindow<>nil then begin
  306.         io:=CloseServiceWindow(storage^.StoredPalletteWindow);
  307.         storage^.StoredPalletteWindow:=nil;
  308.         end;
  309.     end;
  310.  
  311. {--------------------------------------------------------------------------
  312.     
  313.     DrawTheWindow
  314.         Just draw the window.  Note that the ServiceWindow is just a
  315.         window for this purpose.  Since we're calling this from our jGNE
  316.         Event Filter, we are NOT in our owner layer.  So, we don't have our
  317.         A5 world, and our resource file isn't open.  If this was a problem,
  318.         we could go through our IdleProc handler.
  319.         
  320.  
  321.  --------------------------------------------------------------------------}
  322. Procedure DrawTheWindow;
  323. var    thewindow:windowptr;
  324.     index:integer;
  325. begin
  326.     thewindow:=storage^.StoredPalletteWindow;
  327.     if thewindow<>nil then begin
  328.         beginupdate(thewindow);
  329.         setport(thewindow);
  330.         with storage^ do begin {Show all the icons}
  331.             for index:=1 to PalletteIcons do PlotFileIcon(index);
  332.             end;
  333.         endupdate(thewindow);
  334.         end;
  335.     end;
  336.  
  337. {--------------------------------------------------------------------------
  338.     
  339.     OpenPalletteWindow
  340.         Creates the window.  Count processes, create the window, remember the
  341.         processes.
  342.  
  343.  --------------------------------------------------------------------------}
  344. Function OpenPalletteWindow:OSErr;
  345. var    therect:rect;
  346.     thewindow:windowptr;
  347.     s2:str255;
  348.     index,thecount,NumIcons:integer;
  349.     myCPB:CInfoPBRec;
  350.     io:OSErr;
  351.         
  352.         Procedure cio(io:OSErr);
  353.         begin
  354.             if io<>NoErr then begin
  355.                 OpenPalletteWindow:=io;
  356.                 exit(OpenPalletteWindow);
  357.                 end;
  358.             end;
  359.     
  360.     Procedure EnumerateProcesses;
  361.     var io,err:OSErr; psn:ProcessSerialNumber; myinfo:ProcessInfoRec; flag:boolean;
  362.     begin
  363.         io:=GetFrontProcess(storage^.LastProcess);
  364.         storage^.LastProcessIndex:=0;
  365.         psn.highLongOfPSN:=0;
  366.         psn.lowLongOfPSN:=kNoProcess;
  367.         thecount:=0;
  368.         repeat
  369.             io:=GetNextProcess(psn);
  370.             if io=NoErr then begin
  371.                 myinfo.processName:=@s2;
  372.                 myinfo.processInfoLength:=sizeof(myinfo);
  373.                 myinfo.processAppSpec:=nil;
  374.                 io:=GetProcessInformation(psn,myinfo);
  375.                 if io=NoErr then
  376.                     if bitand(myinfo.processMode,modeOnlyBackground)=0 then begin
  377.                         thecount:=thecount+1;
  378.                         with storage^.TheIcon[thecount] do begin
  379.                             name:=s2;
  380.                             TheType:=OSType(myinfo.processType);
  381.                             TheCreator:=myinfo.processSignature;
  382.                             Thepsn:=psn;
  383.                             end;
  384.                         io:=SameProcess(psn,storage^.LastProcess,flag);
  385.                         if flag then storage^.LastProcessIndex:=thecount;
  386.                         if thecount=MaxNumberIcons then exit(EnumerateProcesses);
  387.                         end;
  388.                 end;
  389.             until io<>NoErr;
  390.         end;
  391.  
  392. begin
  393.     OpenPalletteWindow:=NoErr;
  394.     
  395.     EnumerateProcesses;
  396.     storage^.PalletteIcons:=thecount;
  397.     
  398.     if storage^.StoredPalletteWindow<>nil then CloseThePallette;
  399.     with therect do begin
  400.         bottom:=storage^.BottomRight.v; right:=storage^.BottomRight.h;
  401.         if (storage^.PalletteIcons>0) then begin
  402.             top:=bottom-MyItemHeight;
  403.             left:=right-(storage^.PalletteIcons*MyItemWidth);
  404.             end
  405.             else begin
  406.                 left:=right-150;
  407.                 top:=bottom-1;
  408.                 end;
  409.         end;
  410.     cio(NewServiceWindow(nil, therect,'AppBar',true,noGrowDocProc,pointer(-1),true,
  411.         componentInstance(kCurrentProcess),thewindow));
  412.     storage^.StoredPalletteWindow:=thewindow;
  413.     HiliteWindow(thewindow,true);
  414.     end;
  415. {--------------------------------------------------------------------------
  416.     
  417.     RecalcWindow
  418.         We've changed the front process!  If both the new front and old front are in
  419.         my list, just redraw the icons.  Otherwise, recreate the window.
  420.  
  421.  --------------------------------------------------------------------------}
  422. Procedure RecalcWindow;
  423. var    io:OSErr;
  424.     Function IsOK(which:integer):boolean;
  425.     var io,err:OSErr; myinfo:ProcessInfoRec; 
  426.     begin
  427.         myinfo.processName:=nil;
  428.         myinfo.processInfoLength:=sizeof(myinfo);
  429.         myinfo.processAppSpec:=nil;
  430.         IsOK:=(GetProcessInformation(storage^.TheIcon[which].ThePsn,myinfo)=NoErr);
  431.         end;
  432.     Procedure FullRecalc;
  433.     var    io:OSErr;
  434.     begin
  435.         io:=OpenPalletteWindow;
  436.         exit(RecalcWindow);
  437.         end;
  438.     Procedure CheckForNew;
  439.     var    index:integer;
  440.         frontpsn:ProcessSerialNumber;
  441.         io:OSErr;
  442.         flag:boolean;
  443.         oldlast:integer;
  444.         tempport:grafptr;
  445.     begin
  446.         io:=GetFrontProcess(frontpsn);
  447.         with storage^ do begin
  448.             for index:=1 to PalletteIcons do begin
  449.                 io:=SameProcess(frontpsn,TheIcon[index].ThePsn,flag);
  450.                 if io=NoErr then
  451.                     if flag then begin
  452.                         oldlast:=LastProcessIndex;
  453.                         LastProcessIndex:=index;
  454.                         LastProcess:=frontpsn;
  455.                         GetPort(tempport);
  456.                         SetPort(storage^.StoredPalletteWindow);
  457.                         PlotFileIcon(oldlast);
  458.                         PlotFileIcon(index);
  459.                         SetPort(tempport);
  460.                         exit(RecalcWindow);
  461.                         end;
  462.                 end;
  463.             end;
  464.         FullRecalc;
  465.         end;
  466.         
  467. begin
  468.     SystemMenu($BF970002);
  469.     if not IsOK(storage^.LastProcessIndex) then FullRecalc
  470.         else CheckForNew;
  471.     end;
  472. {--------------------------------------------------------------------------
  473.     
  474.     SetWhatToDo
  475.         We don't want to do much from our jGNE Event Filter, because that lives
  476.         in other applications.  So, we set a flag for what to do, and call
  477.         WakeUpProcess to break us out of our long WaitNextEvent.
  478.  
  479.  --------------------------------------------------------------------------}
  480. Procedure SetWhatToDo(thecommand:integer);
  481. var    io:OSErr;
  482. begin
  483.     storage^.WhatToDo:=thecommand;
  484.     io:=WakeUpProcess(storage^.MyProcess);
  485.     end;
  486.  
  487. {--------------------------------------------------------------------------
  488.     
  489.     LayerIdleProc
  490.         Called from our app's main event loop, if there's a flag for a deferred
  491.         action, we handle it now.
  492.         
  493.         We've got a special handlers for quitting when the pallette is
  494.         closed.
  495.         
  496.         If one of our icons have been clicked on, we'll switch to it it here.  We
  497.         might have been able to do it from the frontmost app, but this is
  498.         safer.
  499.  
  500.  --------------------------------------------------------------------------}
  501. Procedure LayerIdleProc(var doneflag:boolean);
  502. var    io:OSErr;
  503. begin
  504.     with storage^ do
  505.         case WhatToDo of
  506.             kClosePallette:doneFlag:=true; {Quit the AppBar}
  507.             kRecalcWindow:RecalcWindow;
  508.             otherwise 
  509.                 if WhatToDo>0 then
  510.                     io:=SetFrontProcess(TheIcon[WhatToDo].Thepsn);
  511.             end;
  512.     storage^.WhatToDo:=0;
  513.     end;
  514.  
  515. {--------------------------------------------------------------------------
  516.     
  517.     myGNEFilter
  518.         This is how we see the events for our window.  It's called from assembler
  519.         glue to jGNEFilter (it's not a trap patching, though I'll admit it's a
  520.         technicallity).
  521.         
  522.         This code executes in the heap and A5 world of whatever the frontmost app
  523.         is, it is NOT likely to be running inside of AppBar.  So, globals should
  524.         be dealt with carefully if at all, and we need to be careful.
  525.         
  526.         We only handle click events.  We can hilite rectangles (but we MUST save and
  527.         restore the port, because it's not our port we're tromping over!) and use
  528.         normal window calls like TrackGoAway and DragWindow.
  529.         
  530.         To detect our clicks, we call a different kind of FindWindow that finds a
  531.         service window.  We then must make sure it's OUR service window (not all
  532.         service windows might be ours).
  533.         
  534.         Once we've handled our events, we must make sure to turn them into null events,
  535.         or they will be passed on to the operating system!
  536.         
  537.         We also check here to see if our window needs updating.  Service Windows
  538.         appear not to get update events, so we have to check manually.  (I could be
  539.         wrong on this, this is what I've discovered so far.)  My update routine doesn't
  540.         use any resources of mine, which is fortunate, because again I'm not really in
  541.         my application's layer.  If this was a problem, I could just flag that an updating
  542.         is necessary and handle it in my application's main event loop.
  543.         
  544.         I also am checking the front process here to see if the system changed it on me, so
  545.         I need to update my window.
  546.         
  547.  --------------------------------------------------------------------------}
  548. Function myGNEFilter (result:integer; var event:EventRecord):integer;
  549. var    tempwindow:windowptr; typefind:integer;
  550.     
  551.     Procedure CheckProcessChanged;
  552.     var    psn:ProcessSerialNumber;
  553.         io:OSErr;
  554.         flag:boolean;
  555.     begin
  556.         io:=GetFrontProcess(psn);
  557.         io:=SameProcess(psn,storage^.LastProcess,flag);
  558.         if not flag then SetWhatToDo(kRecalcWindow);
  559.         end;
  560.     
  561.     Procedure KillEvent;
  562.     begin
  563.         event.what:=nullEvent;
  564.         end;
  565.     
  566.     Procedure HandleDrag;
  567.     var    tempport:Grafptr;
  568.         dragrect:rect;
  569.     begin
  570.         Getport(tempport);
  571.         Setport(tempwindow);
  572.         SetRect(dragRect,-32767,-32767,32767,32767);
  573.         DragWindow(tempWindow,event.where,dragRect);
  574.         with storage^.BottomRight do begin
  575.             h:=tempwindow^.portrect.right;
  576.             v:=tempwindow^.portrect.bottom;
  577.             end;
  578.         LocalToGlobal(storage^.BottomRight);
  579.         Setport(tempport);
  580.         KillEvent;
  581.         end;
  582.     
  583.     Procedure HandleClick;
  584.     var    tempport:Grafptr;
  585.         ThePoint:point;
  586.         AmIn:Boolean;
  587.         TheRect:rect;
  588.         WhichItem:integer;
  589.     begin
  590.         KillEvent;
  591.         Getport(tempport);
  592.         Setport(tempwindow);
  593.         with storage^ do begin
  594.             ThePoint:=event.where;
  595.             GlobalToLocal(ThePoint);
  596.             WhichItem:=(ThePoint.h-tempwindow^.portrect.left) div MyItemWidth+1;
  597.             if (WhichItem>0) and (WhichItem<=PalletteIcons) then begin
  598.                 TheRect:=tempWindow^.portrect;
  599.                 with TheRect do begin
  600.                     left:=(WhichItem-1)*MyItemWidth;
  601.                     right:=left+MyItemWidth;
  602.                     end;
  603.                 BitClr(pointer(HILITEMODE),0);
  604.                 InvertRect(TheRect);
  605.                 AmIn:=true;
  606.                 While WaitMouseUp do begin
  607.                     GetMouse(ThePoint);
  608.                     if PtInRect(ThePoint,TheRect)<>AmIn then begin
  609.                         AmIn:=not AmIn;
  610.                         BitClr(pointer(HILITEMODE),0);
  611.                         InvertRect(TheRect);
  612.                         end;
  613.                     end;
  614.                 if AmIn then begin
  615.                     BitClr(pointer(HILITEMODE),0);
  616.                     InvertRect(TheRect);
  617.                     SetWhatToDo(WhichItem);
  618.                     end;
  619.                 end;
  620.             end;
  621.         SetPort(tempport);
  622.         end;
  623. begin
  624.     if storage^.StoredPalletteWindow<>nil then
  625.         case event.what of
  626.             mouseDown:begin
  627.                 
  628.                 typefind:=FindServiceWindow(event.where,tempWindow);
  629.                 if typefind>inSysWindow then
  630.                     if tempwindow=storage^.StoredPalletteWindow then begin
  631.                         case typefind of
  632.                             inDrag: HandleDrag; 
  633.                             inGoAway: begin
  634.                                 IF TrackGoAway(tempWindow,event.where) THEN
  635.                                     SetWhatToDo(kClosePallette);
  636.                                 KillEvent;
  637.                                 end;
  638.                             inContent: HandleClick;
  639.                             END;
  640.                         end;
  641.                 end;
  642.             
  643.             nullEvent: begin
  644.                 tempwindow:=storage^.StoredPalletteWindow;
  645.                 if tempwindow<>nil then
  646.                     if not EmptyRgn(windowpeek(tempwindow)^.updateRgn) then DrawTheWindow;
  647.                 CheckProcessChanged;
  648.                 end;
  649.             END;    { of event case }
  650.     myGNEFilter:=result;
  651.     end;
  652.  
  653. {--------------------------------------------------------------------------
  654.     
  655.     CloseLayer
  656.         This is called right before quitting.  We MUST close the pallette, if
  657.         we don't, it'll stay around forever and be very annoying.  We also have
  658.         to unhook ourselves from jGNEFilter.  Yes, we could encounter problems if
  659.         someone has hooked jGNEFilter after we did.  I don't have a solution for
  660.         that.
  661.         
  662.  --------------------------------------------------------------------------}
  663. Procedure CloseLayer;
  664. begin
  665.     CloseThePallette;
  666.     UnHook;
  667.     end;
  668.     
  669. {--------------------------------------------------------------------------
  670.     
  671.     InitLayer
  672.         This is called from our setup code to draw the window.  We check to
  673.         make sure that we have the Text Services Manager here, and remember our
  674.         process serial number (so we can call WakeUpProcesson ourself).  Finally,
  675.         we hook ourselves into jGNEFilter so that we can get the events for our
  676.         pallette.
  677.         
  678.  --------------------------------------------------------------------------}
  679. Function InitLayer:OSErr;
  680. var    io:OSErr;
  681.     theresult:longint;
  682. begin
  683.     storage^.WhatToDo:=0;
  684.     InitLayer:=-1;
  685.     if gestalt(gestaltTSMgrVersion,theresult)<>NoErr then exit(InitLayer);
  686.     io:=GetCurrentProcess(storage^.MyProcess);
  687.     
  688.     with storage^.BottomRight do begin
  689.         v:=screenbits.bounds.bottom-10;
  690.         h:=screenbits.bounds.right-40;
  691.         end;
  692.  
  693.     if io=NoErr then HookUp;
  694.     InitLayer:=io;
  695.     end;
  696.  
  697. {--------------------------------------------------------------------------
  698.     
  699.     DoOpenApp;
  700.         In Response to an AppleEvent, open the prefs folder.  If no such
  701.         luck, select the folder.
  702.         
  703.  --------------------------------------------------------------------------}
  704. Procedure DoOpenApp(AllowUserInteraction:Boolean);
  705. var    io:OSErr;
  706. begin
  707.     {Try to open our Prefs folder}
  708.     io:=OpenPalletteWindow;
  709.     end;
  710.  
  711. END.
  712.